using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using TelnetExpect;
using System.IO;

namespace TelnetTests.Ansi
{
    public class TestsAnsi1_OneByteAtATime : TestsAnsi1
    {
        protected override Stream Create_ModifierStream(MemoryStream strm0)
        {
            return new OneByteAtATimeStream(base.Create_ModifierStream(strm0));
        }
    }

    [TestFixture]
    public class TestsAnsi1
    {
        const string ESC = "\x1B";
        const string BRACKET = "[";
        const string Exp_ABCD = "[61][62][63][64]";
        const string Exp_MNOP = "[6D][6E][6F][70]";
        const string Exp_0x1B = "[1B]";

        [Test]
        public void AllText()
        {
            DoTest("abcd", Exp_ABCD);
        }

        [Test]
        public void AllOneControl()
        {
            DoTest(ESC + BRACKET + "H", "[Command 'H']");
        }

        [Test]
        public void Params_AllOneControl()
        {
            DoTest(ESC + BRACKET + "1;2;3H", "[Command 'H' 1-2-3]");
        }

        [Test]
        public void Middle()
        {
            string input
                = "abcd"
                + ESC + BRACKET + "H"
                + "mnop";
            string expected = Exp_ABCD + "[Command 'H']" + Exp_MNOP;
            DoTest(input, expected);
        }

        [Test]
        public void Params_Middle()
        {
            string input
                = "abcd"
                + ESC + BRACKET + "1;1" + "H"
                + "mnop";
            string expected = Exp_ABCD + "[Command 'H' 1-1]" + Exp_MNOP;
            DoTest(input, expected);
        }

        [Test]
        public void TwoControls()
        {
            DoTest(ESC + BRACKET + "j" + ESC + BRACKET + "H", "[Command 'j']" + "[Command 'H']");
        }

        [Test]
        public void TwoControlsOneSe()
        {
            DoTest(ESC + BRACKET + "j" + "a" + ESC + BRACKET + "H", "[Command 'j']" + "[61]" + "[Command 'H']");
        }

        [Test]
        public void EscapeNotFollowedByBracket()
        {
            DoTest(ESC + "abcd", Exp_0x1B + Exp_ABCD);
        }

        //--------
        private void DoTest(string input, string expected)
        {
            byte[] data = Encoding.ASCII.GetBytes(input);
            MemoryStream strm0 = new MemoryStream(data, false);
            Stream strm = Create_ModifierStream(strm0);
            Test1Ansi dut = new Test1Ansi(strm);
            dut.RunPrinterForever();
            dut.AssertResult(expected, "test");
        }

        protected virtual Stream Create_ModifierStream(MemoryStream strm0)
        {
            return strm0;
        }

        class Test1Ansi : AnsiConsoleBase
        {
            StringBuilder m_bldr = new StringBuilder();

            public Test1Ansi(Stream peer)
                : base(peer)
            {
            }

            public void AssertResult(string expected, string name)
            {
                Assert.AreEqual(expected, m_bldr.ToString(), name);
            }

            protected override void OnAnsiCommand(char command, int[] vars)
            {
                StringBuilder varText = new StringBuilder();
                const string Sep = "-";
                Array.ForEach(vars, delegate(int cur) {
                    varText.Append(cur.ToString(System.Globalization.CultureInfo.InvariantCulture));
                    varText.Append(Sep);
                });
                if (varText.Length >= Sep.Length) {
                    varText.Length -= Sep.Length;
                }
                m_bldr.AppendFormat("[Command '{0}'{1}{2}]",
                    command, varText.Length == 0 ? null : " ", varText);
            }

            protected override void OnText(byte[] buf, int offset, int count)
            {
                string textH = BitConverter.ToString(buf, offset, count);
                string text = "[" + textH.Replace("-", "][") + "]";
                m_bldr.Append(text);
            }
        }
    }
}
